import functools
from datetime import datetime, timedelta
from flask import Flask, jsonify
from .printSelf  import printSelf

#将时间戳转换为格式化时间
def setTimeTampToFormatTime(timeTamp):
    """
    将时间戳转换为格式化时间
    :param timeTamp: 时间戳
    :return: 格式化时间
    """
    timeTamp=int(timeTamp)
    dt_object = datetime.fromtimestamp(timeTamp)
    formatted_time = dt_object.strftime('%Y%m%d %H%M%S') #20241227 171400
    return formatted_time
#将时间戳转换为格式化时间,需要给格式
def setTimeTampToFormatTimeAndFormat(timeTamp, format):
    """
    将时间戳转换为格式化时间
    :param timeTamp: 时间戳
    :return: 格式化时间
    """
    timeTamp=int(timeTamp)
    dt_object = datetime.fromtimestamp(timeTamp)
    formatted_time = dt_object.strftime(format) #20241227 171400
    return formatted_time

#判断给定日期是否是休息日
def is_holiday(date):
    """
    排除休息日的情况,休息日包括:周六日,五一3天,十一7天,春节7天,清明节,端午节,中秋节,元旦,不用算的太圆满,只用计算2024-2025年的休息日,就可以了

    判断给定日期是否是休息日（周六、周日或指定节假日）。

    :param date: 要判断的日期。
    :return: 如果是休息日返回True，否则返回False。
    """
    # 定义2024年和2025年的节假日
    holidays = {
        2025: [
            # 元旦
            '2025-01-01',
            # 春节假期 (假设从除夕开始, 具体日期需根据农历调整)
            '2025-01-28', '2025-01-29', '2025-01-30', '2025-01-31',
            '2025-02-01', '2025-02-02', '2025-02-03','2025-02-04',
            # 清明节 (假设日期)
            '2025-04-04',
            # 劳动节
            '2025-05-01', '2025-05-02', '2025-05-03','2025-05-04','2025-05-05'
            # 端午节 (假设日期)
            '2025-06-02',
            # 中秋节 (假设日期)
            # 国庆节
            '2025-10-01', '2025-10-02', '2025-10-03', '2025-10-04',
            '2025-10-05', '2025-10-06', '2025-10-07', '2025-10-08'
        ]
    }

    # 检查是否是周六或周日
    if date.weekday() >= 5:  # 周六(5)或周日(6)
        return True

    # 检查是否在节假日列表中
    holiday_list = holidays.get(date.year, [])
    if date.strftime('%Y-%m-%d') in holiday_list:
        return True

    return False

#定义一个装饰器,用于判断今天是不是休息日,利用上面那个判断函数
def is_rest_day(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        today = datetime.today()  # Monday is 0 and Sunday is 6
        if is_holiday(today):  # Assuming Saturday (5) and Sunday (6) are rest days
            print({"message": "Today is a rest day, function not executed."})
            return None
        else:
            return func(*args, **kwargs)
    return wrapper

#获取交易开始时间的时间戳,参数是时间对象
def getTradingStartTimestamp(specifiedTimeObj=None):
    """
    获取交易开始时间的时间戳。
    如果当前时间的小时小于某个设定值（例如21:00），则返回昨天的该时间点的时间戳。

    :param specifiedTimeObj: 可选的当前时间，默认为None，此时使用系统当前时间。
    :return: 交易开始时间的时间戳。
    """
    # 假设交易开始时间是每天的21:00
    trading_start_hour = 21
    if specifiedTimeObj is None:
        specifiedTimeObj = datetime.now()
    #print(currentTimeObj)

    #如果你给我的日期不是工作日,那么我就要判断这个日期是不是工作日
    targetDate=0
    #printSelf(targetDate,"targetDate")
    tuiSign=False #往前倒车的标志
    while True:
        if is_holiday(specifiedTimeObj): #如果当前时间是休息日,那么我就要往前一天 #然后,再次判断是否是休息日,如果不是休息日,就判断小时是否合适
            specifiedTimeObj -= timedelta(days=1)
            #printSelf(specifiedTimeObj,"currentTimeObj")
            tuiSign=True
        else: #如果当前时间不是休息日,那么我就要判断当时的小时是否小于开始时间
            #printSelf(specifiedTimeObj,"specifiedTimeObj 不是休息日")
            if(tuiSign):#如果倒车标志为真,且这一天是交易日,那我原本给出来的时间,肯定在这个时间以后,那么直接取倒车日的21:00的时间戳就可以了
                targetDate=specifiedTimeObj
            else:#倒车标志为假,且这一天是交易日,那我原本给出来的时间可能在21时之后,或之前
                if specifiedTimeObj.hour < trading_start_hour: #如果我原本给出来的时间小于21时,那么就要往回倒车一天,并重新判断是否是交易日
                    specifiedTimeObj -= timedelta(days=1)
                    while True:
                        if is_holiday(specifiedTimeObj):#如果往前的这个日期是休息日,就要再次往前,如果不是休息日,就可以停了
                            specifiedTimeObj -= timedelta(days=1)
                        else:
                            break
                    targetDate=specifiedTimeObj
                else:#如果我给出来的时间大于等于21时,那么这个给出来的日期就是用来取21点的日期
                    targetDate=specifiedTimeObj
            break
    # 设置交易开始时间为当天的21:00
    #printSelf(targetDate,"targetDate")
    trading_start_time = datetime(
        year=targetDate.year,
        month=targetDate.month,
        day=targetDate.day,
        hour=trading_start_hour,
        minute=0,
        second=0
    )

    # 返回时间戳
    return int(trading_start_time.timestamp())

#将时间字符串转换为时间对象  #20241227 171400
def parseDatetimeFromString(date_str):

    # 定义字符串的格式
    date_format = "%Y%m%d %H%M%S"
    # 使用 strptime 方法将字符串解析为 datetime 对象
    dt = datetime.strptime(date_str, date_format)
    return dt

#将时间字符串 20250508 210000 转换成时间戳
def parseDateStrToTimetamp(date_str):

    # 定义字符串的格式
    date_format = "%Y%m%d %H%M%S"
    # 使用 strptime 方法将字符串解析为 datetime 对象
    dt = datetime.strptime(date_str, date_format)
    return int(dt.timestamp())

#根据给的时间戳,获取活动日的日期字符串
def getDateStrFromTimestamp(timestamp):


    return getTimeObjFromTimestamp(timestamp).strftime("%Y%m%d")

#获取当前时间戳
def getNowTimestamp():
    """
    获取当前时间戳。

    :return: 当前时间戳。
    """
    return int(datetime.now().timestamp())
#获取时间对象的时间戳
def getTimestampFromTimeObj(timeObj):
    """
    获取当前时间戳。

    :return: 当前时间戳。
    """
    return int(timeObj.timestamp())

#获取时间戳对应的时间对象
def getTimeObjFromTimestamp(timestamp):
    """
    将时间戳转换为 datetime 对象。

    :param timestamp: 时间戳。
    :return: datetime 对象。
    """
    return datetime.fromtimestamp(timestamp)


# 获取已经发生的最近1到11个交易日的21:00的时间戳
def get_recent_trading_days_timestamps(n=30):
    current_date = datetime.now()
    timestamps = []

    days_count = 0
    while days_count < n:
        #print(current_date)
        #print(is_holiday(current_date))
        #print(days_count)
        if not is_holiday(current_date):
            trading_day_2100 = current_date.replace(hour=21, minute=0, second=0, microsecond=0)
            timestamps.append(int(trading_day_2100.timestamp()))
            days_count += 1
        current_date -= timedelta(days=1)
    #print(timestamps)
    return timestamps

#根据给定时间戳,获取最近1个交易日的14点时间戳
def get_recent_trading_day_14_timestamp(timestamp):
    #print(timestamp)
    timeObj=getTimeObjFromTimestamp(timestamp)
    #print(timeObj)
    #如果小时小于21:00,那么就往前一天
    if timeObj.hour<21:
        timeObj -= timedelta(days=1)
    timestamps = []
    days_count = 0
    while days_count < 1:
        #print(current_date)
        #print(is_holiday(current_date))
        #print(days_count)
        if not is_holiday(timeObj):
            trading_day_1400 = timeObj.replace(hour=14, minute=0, second=0, microsecond=0)
            timestamps.append(int(trading_day_1400.timestamp()))
            days_count += 1
        timeObj -= timedelta(days=1)
    #print(timestamps[0])
    return timestamps[0]

#根据给定时间戳获取交易日的15:00时间戳
def getTradingEndTimestamp(currentTimeObj=None):
    """
    根据给定时间戳获取工作日的结束时间戳。

    :param currentTimeObj: 给定的时间对象。
    :return: 工作日的结束时间戳（15:00）。
    """
    if currentTimeObj is None:
        currentTimeObj = datetime.now()
    #print(currentTimeObj)
    trading_end_hour = 15

    # 如果给定时间在21:00或之后，从明天开始找
    if currentTimeObj.hour >= 21:
        date = currentTimeObj.date() + timedelta(days=1)
    else:
        date = currentTimeObj.date()

    # 找到下一个非休息日的15:00
    while is_holiday(date):
        date += timedelta(days=1)

    trading_end_time = datetime(date.year, date.month, date.day, trading_end_hour, 0, 0)
    #print(trading_end_time)
    return int(trading_end_time.timestamp())

#判断小时是否是21或9 如果是,那么分钟是不是1-5,这段时间内不开单
def is21or9in0_5(timeObjTamp):
    timeObj = getTimeObjFromTimestamp(timeObjTamp)
    hour = timeObj.hour
    minute = timeObj.minute
    if hour == 21 or hour == 9:
        if minute<=6:
            return True
    else:
        return False

def getTradeTimeStr(dayList):
    year="2025"
    #dayList=["0304","0305","0306","0307","0310"]
    timeList1=["2101","2102","2103","2104","2105","2106","2107","2108","2109","2110","2111","2112","2113","2114","2115","2116","2117","2118","2119","2120","2121","2122","2123","2124","2125","2126","2127","2128","2129","2130","2131","2132","2133","2134","2135","2136","2137","2138","2139","2140","2141","2142","2143","2144","2145","2146","2147","2148","2149","2150","2151","2152","2153","2154","2155","2156","2157","2158","2159","2200","2201","2202","2203","2204","2205","2206","2207","2208","2209","2210","2211","2212","2213","2214","2215","2216","2217","2218","2219","2220","2221","2222","2223","2224","2225","2226","2227","2228","2229","2230","2231","2232","2233","2234","2235","2236","2237","2238","2239","2240","2241","2242","2243","2244","2245","2246","2247","2248","2249","2250","2251","2252","2253","2254","2255","2256","2257","2258","2259","2300"]
    timeList2=["0900","0901","0902","0903","0904","0905","0906","0907","0908","0909","0910","0911","0912","0913","0914","0915","0916","0917","0918","0919","0920","0921","0922","0923","0924","0925","0926","0927","0928","0929","0930","0931","0932","0933","0934","0935","0936","0937","0938","0939","0940","0941","0942","0943","0944","0945","0946","0947","0948","0949","0950","0951","0952","0953","0954","0955","0956","0957","0958","0959","1000","1001","1002","1003","1004","1005","1006","1007","1008","1009","1010","1011","1012","1013","1014","1015","1030","1031","1032","1033","1034","1035","1036","1037","1038","1039","1040","1041","1042","1043","1044","1045","1046","1047","1048","1049","1050","1051","1052","1053","1054","1055","1056","1057","1058","1059","1100","1101","1102","1103","1104","1105","1106","1107","1108","1109","1110","1111","1112","1113","1114","1115","1116","1117","1118","1119","1120","1121","1122","1123","1124","1125","1126","1127","1128","1129","1130","1330","1331","1332","1333","1334","1335","1336","1337","1338","1339","1340","1341","1342","1343","1344","1345","1346","1347","1348","1349","1350","1351","1352","1353","1354","1355","1356","1357","1358","1359","1400","1401","1402","1403","1404","1405","1406","1407","1408","1409","1410","1411","1412","1413","1414","1415","1416","1417","1418","1419","1420","1421","1422","1423","1424","1425","1426","1427","1428","1429","1430","1431","1432","1433","1434","1435","1436","1437","1438","1439","1440","1441","1442","1443","1444","1445","1446","1447","1448","1449","1450","1451","1452","1453","1454","1455","1456","1457","1458","1459","1500"]

    timeStrList=[]
    dayIndex=0
    for dayItem in dayList:
      timeStrListTmp=[]
      for timeItem in timeList1:
          timeStrListTmp.append(year+dayItem+" "+timeItem)
      if dayIndex+1<len(dayList):
        for timeItem in timeList2:
            timeStrListTmp.append(year+dayList[dayIndex+1]+" "+timeItem)
      timeStrList.append(timeStrListTmp)
      dayIndex+=1
    return timeStrList

#从时间戳变成月日,0601
def fromTampToMonthDay(timestamp):
    timeObj=getTimeObjFromTimestamp(timestamp)
    month=timeObj.month
    day=timeObj.day
    if month<10:
        month="0"+str(month)
    if day<10:
        day="0"+str(day)
    return str(month)+str(day)